"""
版本完成度计算服务
负责计算版本关联对象的完成度
"""
from typing import Dict, List, Optional
from datetime import datetime
from motor.motor_asyncio import AsyncIOMotorDatabase  # pyright: ignore[reportMissingImports]
from bson import ObjectId  # pyright: ignore[reportMissingImports]
import logging

logger = logging.getLogger(__name__)


class VersionCompletionService:
    """版本完成度计算服务"""
    
    def __init__(self, db: AsyncIOMotorDatabase):
        self.db = db
    
    async def calculate_completion_rate(self, version_id: ObjectId) -> Dict:
        """
        计算版本完成度
        
        Returns:
        {
            "task_completion": 0.85,
            "defect_completion": 0.90,
            "requirement_completion": 0.80,
            "test_completion": 0.75,
            "overall_completion": 0.825,
            "details": {
                "tasks": {"total": 20, "completed": 17},
                "defects": {"total": 10, "resolved": 9},
                "requirements": {"total": 15, "completed": 12},
                "tests": {"total": 30, "passed": 22, "total_run": 25}
            }
        }
        """
        # 1. 计算任务完成度
        task_stats = await self._calculate_task_completion(version_id)
        
        # 2. 计算缺陷完成度
        defect_stats = await self._calculate_defect_completion(version_id)
        
        # 3. 计算需求完成度
        requirement_stats = await self._calculate_requirement_completion(version_id)
        
        # 4. 计算测试完成度
        test_stats = await self._calculate_test_completion(version_id)
        
        # 5. 计算综合完成度（加权平均）
        overall_completion = self._calculate_overall_completion(
            task_stats, defect_stats, requirement_stats, test_stats
        )
        
        return {
            "task_completion": task_stats["completion_rate"],
            "defect_completion": defect_stats["completion_rate"],
            "requirement_completion": requirement_stats["completion_rate"],
            "test_completion": test_stats["completion_rate"],
            "overall_completion": overall_completion,
            "details": {
                "tasks": task_stats["details"],
                "defects": defect_stats["details"],
                "requirements": requirement_stats["details"],
                "tests": test_stats["details"]
            }
        }
    
    async def _calculate_task_completion(self, version_id: ObjectId) -> Dict:
        """计算任务完成度"""
        # 获取版本关联的所有任务
        relations = await self.db.version_task_relations.find(
            {"version_id": version_id}
        ).to_list(length=None)
        
        if not relations:
            return {
                "completion_rate": 0.0,
                "details": {"total": 0, "completed": 0}
            }
        
        task_ids = [rel["task_id"] for rel in relations]
        
        # 获取已完成状态列表（通过状态模块查询）
        completed_statuses = await self._get_completed_statuses("task")
        
        # 统计任务
        pipeline = [
            {"$match": {"_id": {"$in": task_ids}}},
            {"$group": {
                "_id": None,
                "total": {"$sum": 1},
                "completed": {
                    "$sum": {
                        "$cond": [
                            {"$in": ["$status", completed_statuses]},
                            1,
                            0
                        ]
                    }
                }
            }}
        ]
        
        result = await self.db.tasks.aggregate(pipeline).to_list(length=1)
        
        if result and result[0]:
            stats = result[0]
            total = stats.get("total", 0)
            completed = stats.get("completed", 0)
            completion_rate = completed / total if total > 0 else 1.0
            
            return {
                "completion_rate": completion_rate,
                "details": {"total": total, "completed": completed}
            }
        
        return {
            "completion_rate": 0.0,
            "details": {"total": 0, "completed": 0}
        }
    
    async def _calculate_defect_completion(self, version_id: ObjectId) -> Dict:
        """计算缺陷完成度"""
        # 获取版本关联的所有缺陷
        relations = await self.db.version_defect_relations.find(
            {"version_id": version_id}
        ).to_list(length=None)
        
        if not relations:
            return {
                "completion_rate": 0.0,
                "details": {"total": 0, "resolved": 0}
            }
        
        defect_ids = [rel["defect_id"] for rel in relations]
        
        # 获取已解决状态列表
        resolved_statuses = await self._get_completed_statuses("defect")
        
        # 统计缺陷
        pipeline = [
            {"$match": {"_id": {"$in": defect_ids}}},
            {"$group": {
                "_id": None,
                "total": {"$sum": 1},
                "resolved": {
                    "$sum": {
                        "$cond": [
                            {"$in": ["$status", resolved_statuses]},
                            1,
                            0
                        ]
                    }
                }
            }}
        ]
        
        result = await self.db.defects.aggregate(pipeline).to_list(length=1)
        
        if result and result[0]:
            stats = result[0]
            total = stats.get("total", 0)
            resolved = stats.get("resolved", 0)
            completion_rate = resolved / total if total > 0 else 1.0
            
            return {
                "completion_rate": completion_rate,
                "details": {"total": total, "resolved": resolved}
            }
        
        return {
            "completion_rate": 0.0,
            "details": {"total": 0, "resolved": 0}
        }
    
    async def _calculate_requirement_completion(self, version_id: ObjectId) -> Dict:
        """计算需求完成度"""
        # 获取版本关联的所有需求
        relations = await self.db.version_requirement_relations.find(
            {"version_id": version_id}
        ).to_list(length=None)
        
        if not relations:
            return {
                "completion_rate": 0.0,
                "details": {"total": 0, "completed": 0}
            }
        
        requirement_ids = [rel["requirement_id"] for rel in relations]
        
        # 获取已完成状态列表
        completed_statuses = await self._get_completed_statuses("requirement")
        
        # 统计需求
        pipeline = [
            {"$match": {"_id": {"$in": requirement_ids}}},
            {"$group": {
                "_id": None,
                "total": {"$sum": 1},
                "completed": {
                    "$sum": {
                        "$cond": [
                            {"$in": ["$status", completed_statuses]},
                            1,
                            0
                        ]
                    }
                }
            }}
        ]
        
        result = await self.db.requirements.aggregate(pipeline).to_list(length=1)
        
        if result and result[0]:
            stats = result[0]
            total = stats.get("total", 0)
            completed = stats.get("completed", 0)
            completion_rate = completed / total if total > 0 else 1.0
            
            return {
                "completion_rate": completion_rate,
                "details": {"total": total, "completed": completed}
            }
        
        return {
            "completion_rate": 0.0,
            "details": {"total": 0, "completed": 0}
        }
    
    async def _calculate_test_completion(self, version_id: ObjectId) -> Dict:
        """计算测试完成度（测试通过率）"""
        # 获取版本关联的所有测试用例
        # 注意：如果项目中有版本测试用例关联表，使用该表；否则可能需要通过需求关联来获取
        # 这里假设有 version_test_case_relations 表
        relations = await self.db.version_test_case_relations.find(
            {"version_id": version_id}
        ).to_list(length=None)
        
        if not relations:
            return {
                "completion_rate": 0.0,
                "details": {"total": 0, "passed": 0, "total_run": 0}
            }
        
        test_case_ids = [rel.get("test_case_id") for rel in relations if rel.get("test_case_id")]
        
        if not test_case_ids:
            return {
                "completion_rate": 0.0,
                "details": {"total": 0, "passed": 0, "total_run": 0}
            }
        
        # 获取测试执行结果
        # 假设有 test_case_executions 表存储执行结果
        pipeline = [
            {"$match": {"test_case_id": {"$in": test_case_ids}}},
            {"$group": {
                "_id": "$test_case_id",
                "last_result": {"$last": "$result"},  # 获取最后一次执行结果
                "execution_count": {"$sum": 1}
            }},
            {"$group": {
                "_id": None,
                "total": {"$sum": 1},
                "total_run": {"$sum": 1},
                "passed": {
                    "$sum": {
                        "$cond": [
                            {"$eq": ["$last_result", "passed"]},
                            1,
                            0
                        ]
                    }
                }
            }}
        ]
        
        try:
            result = await self.db.test_case_executions.aggregate(pipeline).to_list(length=1)
            
            if result and result[0]:
                stats = result[0]
                total = stats.get("total", 0)
                total_run = stats.get("total_run", 0)
                passed = stats.get("passed", 0)
                completion_rate = passed / total_run if total_run > 0 else 0.0
                
                return {
                    "completion_rate": completion_rate,
                    "details": {"total": total, "passed": passed, "total_run": total_run}
                }
        except Exception as e:
            logger.warning(f"计算测试完成度失败（可能没有测试执行表）: {str(e)}")
        
        # 如果没有测试执行表，返回基于测试用例总数的统计
        total_tests = len(test_case_ids)
        return {
            "completion_rate": 0.0,
            "details": {"total": total_tests, "passed": 0, "total_run": 0}
        }
    
    def _calculate_overall_completion(
        self,
        task_stats: Dict,
        defect_stats: Dict,
        requirement_stats: Dict,
        test_stats: Dict
    ) -> float:
        """
        计算综合完成度（加权平均）
        权重：任务30%，缺陷20%，需求30%，测试20%
        """
        weights = {
            "task": 0.30,
            "defect": 0.20,
            "requirement": 0.30,
            "test": 0.20
        }
        
        weighted_sum = 0.0
        total_weight = 0.0
        
        if task_stats["details"].get("total", 0) > 0:
            weighted_sum += task_stats["completion_rate"] * weights["task"]
            total_weight += weights["task"]
        if defect_stats["details"].get("total", 0) > 0:
            weighted_sum += defect_stats["completion_rate"] * weights["defect"]
            total_weight += weights["defect"]
        if requirement_stats["details"].get("total", 0) > 0:
            weighted_sum += requirement_stats["completion_rate"] * weights["requirement"]
            total_weight += weights["requirement"]
        if test_stats["details"].get("total", 0) > 0 or test_stats["details"].get("total_run", 0) > 0:
            weighted_sum += test_stats["completion_rate"] * weights["test"]
            total_weight += weights["test"]
        
        if total_weight == 0:
            return 0.0
        
        overall = weighted_sum / total_weight
        return round(overall, 4)
    
    async def _get_completed_statuses(self, module_type: str) -> List[str]:
        """获取已完成状态列表（通过状态模块查询）"""
        try:
            from app.core.state_cache import state_cache
            
            # 获取模块的所有状态
            states = await state_cache.get_module_states(self.db, module_type)
            
            # 使用 state_utils 获取完成状态列表
            from app.utils.state_utils import get_completed_state_codes
            completed_statuses = await get_completed_state_codes(self.db, module_type)
            return completed_statuses
        except Exception as e:
            logger.warning(f"获取{module_type}完成状态失败: {str(e)}")
            return []
    
    async def calculate_readiness_metrics(self, version_id: ObjectId, version: Optional[Dict] = None) -> Dict:
        """
        计算版本准备度指标（用于早期状态判断）
        
        Returns:
        {
            "has_planned_release_date": True,
            "has_description": True,
            "requirement_count": 5,
            "task_count": 8,
            "assigned_task_count": 6,
            "active_task_count": 3
        }
        """
        if version is None:
            version = await self.db.versions.find_one({"_id": version_id})
            if not version:
                return {}
        
        # 检查计划发布日期
        has_planned_release_date = version.get("planned_release_date") is not None
        
        # 检查描述
        has_description = bool(version.get("description"))
        
        # 统计需求数量
        requirement_count = await self.db.version_requirement_relations.count_documents(
            {"version_id": version_id}
        )
        
        # 统计任务数量
        task_relations = await self.db.version_task_relations.find(
            {"version_id": version_id}
        ).to_list(length=None)
        task_count = len(task_relations)
        
        task_ids = [rel["task_id"] for rel in task_relations] if task_relations else []
        
        # 统计已分配的任务数
        assigned_task_count = 0
        active_task_count = 0
        
        if task_ids:
            # 获取已分配的任务
            assigned_tasks = await self.db.tasks.find(
                {"_id": {"$in": task_ids}, "assignee_id": {"$exists": True, "$ne": None}}
            ).to_list(length=None)
            assigned_task_count = len(assigned_tasks)
            
            # 获取活跃状态的任务（非待办、非完成）
            active_statuses = await self._get_active_statuses("task")
            active_tasks = await self.db.tasks.find(
                {"_id": {"$in": task_ids}, "status": {"$in": active_statuses}}
            ).to_list(length=None)
            active_task_count = len(active_tasks)
        
        return {
            "has_planned_release_date": has_planned_release_date,
            "has_description": has_description,
            "requirement_count": requirement_count,
            "task_count": task_count,
            "assigned_task_count": assigned_task_count,
            "active_task_count": active_task_count
        }
    
    async def _get_active_statuses(self, module_type: str) -> List[str]:
        """获取活跃状态列表（非待办、非完成的状态）"""
        try:
            from app.core.state_cache import state_cache
            
            states = await state_cache.get_module_states(self.db, module_type)
            
            # 获取完成状态和待办状态，然后排除它们
            from app.utils.state_utils import get_completed_state_codes, get_state_code_by_name_keywords
            completed_statuses = await get_completed_state_codes(self.db, module_type)
            todo_code = await get_state_code_by_name_keywords(self.db, module_type, ["待办", "todo", "新建", "new"])
            
            # 获取所有启用状态，排除完成状态和待办状态
            active_statuses = []
            for state in states:
                if state.is_enabled and state.code not in completed_statuses:
                    if todo_code and state.code != todo_code:
                        active_statuses.append(state.code)
                    elif not todo_code:
                        active_statuses.append(state.code)
            
            return active_statuses
        except Exception as e:
            logger.warning(f"获取{module_type}活跃状态失败: {str(e)}")
            return []

